在以下代码中,do! ag.AsyncAdd (Some i)
或ag.AsyncAdd (Some i)
(在函数中enqueue()
)均起作用。它们之间有什么区别?似乎do! ...
会使入队和出队电话更加混杂?怎么样?
open FSharpx.Control let test () = let ag = new BlockingQueueAgent(500) let enqueue() = async { for i = 1 to 15 do // ag.AsyncAdd (Some i) // works too do! ag.AsyncAdd (Some i) printfn "=> %d" i } async { do! [ for i = 1 to 10 do yield enqueue() ] |> Async.Parallel |> Async.Ignore for i = 1 to 5 do ag.Add None } |> Async.Start let rec dequeue() = async { let! m = ag.AsyncGet() match m with | Some v -> printfn "<= %d" v return! dequeue() | None -> printfn "Done" } [ for i = 1 to 5 do yield dequeue() ] |> Async.Parallel |> Async.Ignore |> Async.RunSynchronously 0
rmunn.. 6
在任何F#计算表达式中,任何以结尾结尾的关键字都!
倾向于表示“根据此块的规则专门处理此问题”。例如,在一个async { }
块中,let!
关键字的含义是“等待结果,然后将结果分配给此变量”,do!
关键字的含义是“等待此异步操作,但丢弃结果,而不将其分配给任何对象”。如果您不使用do!
关键字,那么您就不在等待该操作的结果。
因此,使用函数中的do!
关键字enqueue
,您将执行以下十五次:
开始一项AsyncAdd
手术
等待它完成
打印“ => 1”(或2或3 ...)
如果没有一个do!
关键字,你正在做的情况如下:
AsyncAdd
尽快开始15项操作
逐一踢完后,打印“ => 1”(或2或3 ...)
听起来您似乎还不完全了解F#的计算表达式在后台如何工作。我建议阅读Scott Wlaschin的优秀网站以获取更多了解:首先https://fsharpforfunandprofit.com/posts/concurrency-async-and-parallel/然后是https://fsharpforfunandprofit.com/series/computation-expressions.html,当您阅读第二系列文章时,您将以一些现有知识为基础。
在任何F#计算表达式中,任何以结尾结尾的关键字都!
倾向于表示“根据此块的规则专门处理此问题”。例如,在一个async { }
块中,let!
关键字的含义是“等待结果,然后将结果分配给此变量”,do!
关键字的含义是“等待此异步操作,但丢弃结果,而不将其分配给任何对象”。如果您不使用do!
关键字,那么您就不在等待该操作的结果。
因此,使用函数中的do!
关键字enqueue
,您将执行以下十五次:
开始一项AsyncAdd
手术
等待它完成
打印“ => 1”(或2或3 ...)
如果没有一个do!
关键字,你正在做的情况如下:
AsyncAdd
尽快开始15项操作
逐一踢完后,打印“ => 1”(或2或3 ...)
听起来您似乎还不完全了解F#的计算表达式在后台如何工作。我建议阅读Scott Wlaschin的优秀网站以获取更多了解:首先https://fsharpforfunandprofit.com/posts/concurrency-async-and-parallel/然后是https://fsharpforfunandprofit.com/series/computation-expressions.html,当您阅读第二系列文章时,您将以一些现有知识为基础。